import * as method from "@mac-xiang/method";

import { oa, ns, typeField, typeFieldMember } from "./itf";
import { methodMerge, methodIn } from "./fun";

export class MysqlObject {
  [propName: string]: any;
  constructor (param: oa) {

  }
}

const int8 = Math.pow(2, 7);
const int16 = Math.pow(2, 15);
const int32 = Math.pow(2, 31);
const int64 = Math.pow(2, 63);
const intType = {
  int8: [0 - int8, int8 - 1],
  uint8: [0, (int8 * 2) - 1],
  int16: [0 - int16, int16 - 1],
  uint16: [0, (int16 * 2) - 1],
  int32: [0 - int32, int32 - 1],
  uint32: [0, (int32 * 2) - 1],
  int: [0 - int32, int32 - 1],
  uint: [0, (int32 * 2) - 1],
  int64: [0 - int64, int64 - 1],
  uint64: [0, (int64 * 2) - 1],
};
export const mtd = {
  "=": (a: Where) => { return methodMerge(a); },
  ">": (a: Where) => { return methodMerge(a); },
  "<": (a: Where) => { return methodMerge(a); },
  ">=": (a: Where) => { return methodMerge(a); },
  "<=": (a: Where) => { return methodMerge(a); },
  "!=": (a: Where) => { return methodMerge(a); },
  "in": (a: Where) => { return methodIn(a); },
  "nin": (a: Where) => { return methodIn(a, true); },
  "regexp": methodMerge,
  "like": (a: Where) => { return ` %'${methodMerge(a)}'%`; }
};
export type mtdK = keyof typeof mtd;
export const curd = {
  0: "SELECT", 1: "UPDATE", 2: "INSERT INTO", 3: "DELETE FROM",
  get: 0, up: 1, add: 2, del: 3,
  r: 0, u: 1, c: 2, d: 3,
  read: 0, update: 1, create: 2, delete: 3
};

export class Where {
  field = "";
  logic: "and" | "or" = "and";
  method: mtdK = "=";
  value: ns | ns[] = "";
  string = "";
  type: typeFieldMember = [0, 0];
  readonly check: boolean = false;
  constructor (param: any, field: typeField) {
    if (param instanceof Literal) {
      this.string = param.value;
      this.check = true;
    }
    if (param instanceof Where) {
      Object.assign(this, param);
    } else if (param && method.isNst(param.field) && (method.isNS(param.value) || Array.isArray(param.value))) {
      this.field = param.field;
      this.logic = param.logic != "or" ? "and" : "or";
      if (Array.isArray(param.value) && param.method != "nin") param.method = "in";
      else if (!param.method || typeof param.method != "string" || !mtd[param.method as mtdK]) param.method = "=";
      this.method = param.method;
      this.value = param.value;
      this.type = field[this.field];
      this.string = mtd[this.method](this);
      this.check = true;
    }
  }
}
export class Literal {
  value: string = "";
  field = "";
  constructor (p: string) {
    if (typeof p == "string") this.value = p;
  }
}

export default { MysqlObject, Where };